﻿using JWT;
using JWT.Algorithms;
using JWT.Exceptions;
using JWT.Serializers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Tauren.Business.Entity.Global; 

namespace Tauren.Business.Infrastructure.Common
{
    public class JWTHelp
    { /// <summary>
      /// JWT解密算法(新的7.x版本写法）
      /// </summary>
      /// <param name="token">需要解密的token串</param>
      /// <param name="secret">密钥</param>
      /// <returns></returns>
        public static IDictionary<string, object> JWTJieM(string token, string secret,string url)
        {
            var webClient = new WebClient();
            var endpoint = $"{url}/.well-known/openid-configuration";
            var json = webClient.DownloadString(endpoint);

            JObject metadata = JsonConvert.DeserializeObject<JObject>(json);

            var jwksUri = metadata["jwks_uri"].ToString();

            //从jwks_uri获取keys
            json = webClient.DownloadString(jwksUri);

            var keys = JsonConvert.DeserializeObject<CustomKeys>(json);


            //从jwt获取头部kid,并从keys中找到匹配kid的key
            string[] tokenParts = token.Split('.');
            byte[] bytes = FromBase64Url(tokenParts[0]);
            string head = Encoding.UTF8.GetString(bytes);
            string kid = JsonConvert.DeserializeObject<JObject>(head)["kid"].ToString();

            var defaultkey = keys.keys.Where(t => t.kid == kid).FirstOrDefault();

            if (defaultkey == null)
            {
                throw new Exception("未找到匹配的kid");
            }
            //jwt解密
            return RS256Decode(token, secret, defaultkey.e, defaultkey.n);
        }
        public static byte[] FromBase64Url(string base64Url)
        {
            string padded = base64Url.Length % 4 == 0
                ? base64Url : base64Url + "====".Substring(base64Url.Length % 4);
            string base64 = padded.Replace("_", "/")
                                  .Replace("-", "+");
            return Convert.FromBase64String(base64);
        }
        public static IDictionary<string, object> RS256Decode(string token, string secret, string exponent, string modulus)
        {
            try
            {
                IJsonSerializer serializer = new JsonNetSerializer();
                IDateTimeProvider provider = new UtcDateTimeProvider();
                IJwtValidator validator = new JwtValidator(serializer, provider);
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                RSAlgorithmFactory rS256Algorithm = new RSAlgorithmFactory(() =>
                {
                    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                    rsa.ImportParameters(
                      new RSAParameters()
                      {
                          Modulus = FromBase64Url(modulus),
                          Exponent = FromBase64Url(exponent)
                      });


                    byte[] rsaBytes = rsa.ExportCspBlob(true);

                    X509Certificate2 cert = new X509Certificate2(rsaBytes);
                    return cert;
                });

                IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, rS256Algorithm);
                var json = decoder.DecodeToObject(token, secret, verify: false);
                return json;
            }
            catch (TokenExpiredException)
            {
                throw new Exception("token已过期");
                //Console.WriteLine("Token has expired");
                //return null;
            }
            catch (SignatureVerificationException)
            {
                throw new Exception("token验证失败");
                //Console.WriteLine("Token has invalid signature");
                //return null;
            }
        }
    }
}
